package com.smy.jkds.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.smy.jkds.po.*;
import com.smy.jkds.vo.*;
import com.smy.jkds.service.CardService;
import com.smy.jkds.service.TTaskRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
 * @author z01140
 * @Package: com.smy.jkds.controller
 * @Description:
 * @CreateDate 2021/10/30 18:03
 * @UpdateDate 2021/10/30 18:03
 */
@Slf4j
@RestController
@RequestMapping("/jkds")
public class UserSpaceController {
    @Autowired
    private TTaskRecordService taskRecordService;
    @Autowired
    private CardService cardService;
    ExecutorService pool = new ThreadPoolExecutor(3, 150, 20L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());


    @GetMapping("/userSpace")
    public Result userSpace(@CurrentUser JkdsUser user, String createDate){

        String startDate = "20210101";
        String endDate = "20211030";
        createDate = createDate == null ? LocalDate.now().plusDays(-1L).format(DateTimeFormatter.ofPattern("yyyyMMdd")) : createDate;
        String finalCreateDate = createDate;
        UserSpaceVO userSpaceVO = new UserSpaceVO();

        List<Callable<Boolean>> callables = new ArrayList<>();
        callables.add(() ->{
            long s = System.currentTimeMillis();
            userSpaceVO.setHeatmapVOS(heatmapVOS(user, startDate, endDate));
            log.info("heatmapVOS: {} ms", System.currentTimeMillis()-s);
            return Boolean.TRUE;
        });
         callables.add(() ->{
             long s = System.currentTimeMillis();
             userSpaceVO.setTaskVOList(taskRecordService.taskVOList(user, finalCreateDate, null));
             log.info("taskVOList: {} ms", System.currentTimeMillis()-s);
            return Boolean.TRUE;
        });
         callables.add(() ->{
             long s = System.currentTimeMillis();
             userSpaceVO.setYearStatisticInfoVO(yearStatisticInfoVO(user));
             log.info("yearStatisticInfoVO: {} ms", System.currentTimeMillis()-s);
            return Boolean.TRUE;
        });
        try {
            pool.invokeAll(callables);
        } catch (Exception e){
            log.error("", e);
        }
        return Result.success("", userSpaceVO);

    }

    YearStatisticInfoVO yearStatisticInfoVO(JkdsUser user) {
        YearStatisticInfoVO yearStatisticInfoVO = new YearStatisticInfoVO();
        try {
            QueryWrapper<TTaskRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(TTaskRecord.ColumnEnum.user_id.name(), user.getId());
            LocalDate now = LocalDate.now();
            LocalDate end = LocalDate.of(now.getYear(), 12,31);
            LocalDate start = LocalDate.of(now.getYear(), 1,1);
            queryWrapper.ge(TTaskRecord.ColumnEnum.create_date.name(), start.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            queryWrapper.le(TTaskRecord.ColumnEnum.create_date.name(), end.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            yearStatisticInfoVO.setTaskCount(taskRecordService.count(queryWrapper));

            QueryWrapper<Card> cardQueryWrapper = new QueryWrapper<>();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            cardQueryWrapper.ge(Card.ColumnEnum.create_time.name(),
                    sdf.parse(start.format(DateTimeFormatter.ofPattern("yyyyMMdd")))
            );
            cardQueryWrapper.le(Card.ColumnEnum.create_time.name(),
                    sdf.parse(end.format(DateTimeFormatter.ofPattern("yyyyMMdd")))
            );
            cardQueryWrapper.ge(Card.ColumnEnum.user_id.name(), user.getId());
            yearStatisticInfoVO.setCardCount(cardService.count(cardQueryWrapper));

            queryWrapper.select("distinct " + TTaskRecord.ColumnEnum.create_date.name());
            yearStatisticInfoVO.setDayCount(taskRecordService.count(queryWrapper));
        } catch (Exception e){
            log.error("", e);
        }
        return yearStatisticInfoVO;
    }

    List<HeatmapVO> heatmapVOS(JkdsUser user, String startDate, String endDate){
        LocalDate now = LocalDate.now();
        LocalDate end = LocalDate.of(now.getYear(), 12,31);
        LocalDate start = LocalDate.of(now.getYear(), 1,1);

        TaskCondition taskCondition = new TaskCondition();
        taskCondition.setStartDate(start.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        taskCondition.setEndDate(end.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        taskCondition.setUserId(user.getId());
        QueryWrapper<TTaskRecord> queryWrapper = new QueryWrapper();
        queryWrapper.eq(TTaskRecord.ColumnEnum.user_id.name(), taskCondition.getUserId());
        queryWrapper.ge(TTaskRecord.ColumnEnum.create_date.name(), taskCondition.getStartDate());
        queryWrapper.le(TTaskRecord.ColumnEnum.create_date.name(), taskCondition.getEndDate());
        List<TTaskRecord> tTaskRecordList =  taskRecordService.list(queryWrapper);
        Map<String, List<TTaskRecord>> groupTask = tTaskRecordList.stream().collect(Collectors.groupingBy(TTaskRecord::getCreateDate));

        Map<String, Integer> groupTaskCount = new HashMap<>();
        AtomicInteger maxCount = new AtomicInteger(Integer.MIN_VALUE);
        groupTask.entrySet().forEach(e -> {
            groupTaskCount.put(e.getKey(), e.getValue().size());
            maxCount.set(maxCount.get() > e.getValue().size() ? maxCount.get() : e.getValue().size());
        });

        LocalDate next = start;
        List<HeatmapVO> heatmapVOS = new ArrayList<>();
        while (!next.isAfter(end)){
            String dateStr = next.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            heatmapVOS.add(HeatmapVO.getInstance(next, groupTaskCount.getOrDefault(dateStr, 0), maxCount.get()));
            next = next.plusDays(1L);
        }
        return heatmapVOS;
    }
}
